package com.liuxvru.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liuxvru.common.constant.WorkConstants;
import com.liuxvru.common.utils.SecurityUtils;
import com.liuxvru.project.domain.*;
import com.liuxvru.project.mapper.*;
import com.liuxvru.project.service.ITestService;
import com.liuxvru.project.service.IWorkService;
import com.liuxvru.project.vo.WorkAllInitVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 工作项Service业务层处理
 *
 * @author liuxvru
 * @date 2024-11-22
 */
@Service
public class WorkServiceImpl extends ServiceImpl<WorkMapper, Work> implements IWorkService {
    @Autowired
    private SprintMapper sprintMapper;
    @Autowired
    private TestMapper TestMapper;
    @Autowired
    private FlawMapper flawMapper;
    @Autowired
    private TestMapper testMapper;
    @Autowired
    private ITestService testService;
    @Autowired
    private WorkAttachmentMapper workAttachmentMapper;
    @Autowired
    private WorkMapper workMapper;

    /**
     * 查询工作项列表
     *
     * @param work 工作项
     * @return 工作项
     */
    @Override
    public List<Work> selectWorkList(Work work) {
        return baseMapper.selectWorkList(work);
    }

    @Override
    public List<Work> getWorkByProjectId(Long projectId) {
        return baseMapper.selectList(new LambdaQueryWrapper<>(Work.class).eq(Work::getProjectId, projectId));
    }

    @Override
    public int add(Work work) {
        work.setCreatedBy(SecurityUtils.getUserId());
        work.setStatus(WorkConstants.WORK_STATUS_OPEN);
        work.setUpdatedBy(SecurityUtils.getUserId());
        Work parentWork = baseMapper.selectById(work.getParentItemId());
        if (parentWork != null) {
            parentWork.setChildCount(parentWork.getChildCount() + 1);
            baseMapper.updateById(parentWork);
        }
        return baseMapper.insert(work);
    }

    @Override
    public List<Work> getWorkBySprintId(Long sprintId) {
        return baseMapper.selectList(new LambdaQueryWrapper<>(Work.class).eq(Work::getSprintId, sprintId));
    }

    @Override
    public List<Work> getWorkByNoSprintId(Long projectId) {
        return baseMapper.selectList(new LambdaQueryWrapper<>(Work.class).isNull(Work::getSprintId).eq(Work::getProjectId, projectId));
    }

    @Transactional
    @Override
    public int workAddSprintByIds(Long sprintId, List<Long> workIds) {
        //更新工作项的sprintId
        //获取当前用户id
        Long userId = SecurityUtils.getUserId();
        Sprint sprint = sprintMapper.selectById(sprintId);
        baseMapper.selectBatchIds(workIds).forEach(work -> {
            if (!Objects.equals(work.getProjectId(), sprint.getProjectId()))
                throw new RuntimeException("工作项不属于当前项目");
        });
        LambdaUpdateWrapper<Work> set = new LambdaUpdateWrapper<>(Work.class).in(Work::getWorkItemId, workIds).set(Work::getSprintId, sprintId).set(Work::getUpdatedBy, userId);
        if (sprint.getReleaseId() != null) {
            set.set(Work::getReleaseId, sprint.getReleaseId());
        }
        baseMapper.update(null, set);
        return 1;
    }

    /**
     * 移除工作项的迭代
     *
     * @param sprintId
     * @param workIds
     * @return
     */
    @Transactional
    @Override
    public int workRemoveSprintByIds(Long sprintId, List<Long> workIds) {
        Long userId = SecurityUtils.getUserId();
        Sprint sprint = sprintMapper.selectById(sprintId);
        baseMapper.selectBatchIds(workIds).forEach(work -> {
            if (!Objects.equals(work.getProjectId(), sprint.getProjectId()))
                throw new RuntimeException("工作项不属于当前项目");
        });
        return baseMapper.update(null, new LambdaUpdateWrapper<>(Work.class).in(Work::getWorkItemId, workIds).set(Work::getSprintId, null).set(Work::getReleaseId, null).set(Work::getUpdatedBy, userId));
    }

    @Override
    public List<Work> listNeed(Long projectId, Work work) {
        work.setProjectId(projectId);
        List<Work> works = baseMapper.selectWorkList(work);
        return works.stream().filter(workItem -> WorkConstants.WORK_TYPE_EPIC.equals(workItem.getType()) || WorkConstants.WORK_TYPE_FEATURE.equals(workItem.getType()) || WorkConstants.WORK_TYPE_USER_STORY.equals(workItem.getType())).collect(Collectors.toList());
    }

    @Override
    public int updateWorkById(Work work) {
        Long userId = SecurityUtils.getUserId();
        Work find = baseMapper.selectById(work.getWorkItemId());
        if (find == null) throw new RuntimeException("工作项不存在");
        if (!Objects.equals(userId, find.getCreatedBy()) && !Objects.equals(userId, find.getAssignee()))
            throw new RuntimeException("无权限修改");
        LambdaUpdateWrapper<Work> workLambdaUpdateWrapper = new LambdaUpdateWrapper<Work>().eq(Work::getWorkItemId, work.getWorkItemId());
        work.setUpdatedBy(userId);
        work.setProjectId(null);
        work.setCreatedBy(null);
        //sprint修改
        if (!Objects.equals(find.getSprintId(), work.getSprintId())) {
            workLambdaUpdateWrapper.set(Work::getSprintId, work.getSprintId());
            if (work.getSprintId() != null) {
                Sprint sprint = sprintMapper.selectById(work.getSprintId());
                if (sprint != null) {
                    workLambdaUpdateWrapper.set(Work::getReleaseId, sprint.getReleaseId());
                }
            } else {
                workLambdaUpdateWrapper.set(Work::getReleaseId, null);
            }
        }
        if (getWorkIsOK(work)!=getWorkIsOK(find)&&find.getParentItemId()!=0L) {
            //状态改为完成
            Work parentWork = baseMapper.selectById(find.getParentItemId());
            parentWork.setUpdatedBy(userId);
            if (getWorkIsOK(work)) {
                work.setCompletedBy(userId);
                work.setCompletedAt(new Date());
                parentWork.setChildCompletedCount(parentWork.getChildCompletedCount() + 1);
            } else {
                workLambdaUpdateWrapper.set(Work::getCompletedBy, null);
                workLambdaUpdateWrapper.set(Work::getCompletedAt, null);
                parentWork.setChildCompletedCount(parentWork.getChildCompletedCount() - 1);
            }
            baseMapper.updateById(parentWork);
        }

        return baseMapper.update(work, workLambdaUpdateWrapper);
    }

    /**
     * 查看工作项是否已经完成（关闭，已完成）
     * @param work 工作项
     * @return 是否已经完成
     */
    private Boolean getWorkIsOK(Work work) {
        return WorkConstants.WORK_STATUS_COMPLETE.equals(work.getStatus()) || WorkConstants.WORK_STATUS_CLOSE.equals(work.getStatus());

    }

    /**
     * 删除任务
     *
     * @param workItemId
     * @return
     */
    @Override
    @Transactional
    public int remove(Long workItemId) {
        Work find = baseMapper.selectById(workItemId);
        Long userId = SecurityUtils.getUserId();
        if (!Objects.equals(find.getAssignee(), userId) && !Objects.equals(find.getCreatedBy(), userId))
            throw new RuntimeException("无权限删除");
        List<Work> works = baseMapper.selectList(new LambdaQueryWrapper<Work>().eq(Work::getParentItemId, workItemId));
        if (!works.isEmpty()) throw new RuntimeException("存在子任务，无法删除");
        int i = baseMapper.deleteById(workItemId);
        if (i == 0) throw new RuntimeException("删除失败");
        if (find.getParentItemId() != 0L) {
            Work parent = baseMapper.selectById(find.getParentItemId());
            if (parent == null) throw new RuntimeException("删除失败");
            parent.setChildCount(parent.getChildCount() - 1);
            if (WorkConstants.WORK_STATUS_COMPLETE.equals(find.getStatus()))
                parent.setChildCompletedCount(parent.getChildCompletedCount() - 1);
            baseMapper.updateById(parent);
        }
        List<Test> tests = testMapper.selectList(new LambdaQueryWrapper<Test>().eq(Test::getWorkItemId, workItemId));
        List<Long> ids = tests.stream().map(Test::getTestId).collect(Collectors.toList());
        //删除测试
        testService.delTests(ids);
        workAttachmentMapper.delete(new LambdaQueryWrapper<WorkAttachment>().in(WorkAttachment::getWorkId, ids));

        return 1;
    }

    /**
     * 获取工作项所有信息，包括测试，附件，缺陷，子任务
     *
     * @param workItemId
     * @return
     */
    @Override
    public WorkAllInitVo workAllInit(Long workItemId) {
        Work work = baseMapper.selectById(workItemId);
        if (work == null) throw new RuntimeException("工作项不存在");
        List<Test> tests = testMapper.selectList(new LambdaQueryWrapper<Test>().eq(Test::getWorkItemId, workItemId));
        List<WorkAttachment> workAttachments = workAttachmentMapper.selectList(new LambdaQueryWrapper<WorkAttachment>().eq(WorkAttachment::getWorkId, workItemId));
        List<Flaw> flaws = flawMapper.selectList(new LambdaQueryWrapper<Flaw>().eq(Flaw::getWorkItemId, workItemId));
        List<Work> childWorks = baseMapper.selectList(new LambdaQueryWrapper<Work>().eq(Work::getParentItemId, workItemId));
        WorkAllInitVo workAllInitVo = new WorkAllInitVo();
        workAllInitVo.setWork(work);
        workAllInitVo.setTests(tests);
        workAllInitVo.setWorkAttachments(workAttachments);
        workAllInitVo.setFlaws(flaws);
        workAllInitVo.setChildWorks(childWorks);
        return workAllInitVo;
    }

}
